package com.giscloud.amp.service.auth.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.giscloud.amp.core.ServiceConstConfig;
import com.giscloud.amp.dao.*;
import com.giscloud.amp.entity.*;
import com.giscloud.amp.entity.dto.AmpAuthDTO;
import com.giscloud.amp.entity.dto.AmpStaffAuthRelDTO;
import com.giscloud.amp.entity.vo.*;
import com.giscloud.amp.service.auth.AmpAuthService;
import com.giscloud.commons.utils.FastJsonUtils;
import com.giscloud.commons.utils.ListUtils;
import com.giscloud.commons.utils.UUIDUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author:gxd
 * @Description: 权限服务类
 * @Date: 17:19 2018/2/24
 * @Modified By:
 */
@Service("ampAuthService")
@CacheConfig(cacheNames ="amp:ampAuthService")
public class AmpAuthServiceImpl implements AmpAuthService {
    private final static Logger log = LoggerFactory.getLogger(AmpAuthServiceImpl.class);
    @Autowired
    private AmpAuthMapper ampAuthMapper;
    @Autowired
    private AmpStaffAuthMapper ampStaffAuthMapper;
    @Autowired
    private SysRegisterMapper sysRegisterMapper;
    @Autowired
    private AmpRoleMapper ampRoleMapper;
    @Autowired
    private AmpStaffRoleMapper ampStaffRoleMapper;
    @Autowired
    private ServiceConstConfig serviceConstConfig;

     @Override
    public List<AmpAuthVO> getAllAmpAuth() {
        AmpAuthExample ampAuthExample = new AmpAuthExample();
         ampAuthExample.createCriteria().andStatusCdEqualTo(1);
        return ampAuthMapper.selectByExample(ampAuthExample);
    }

     @Override
    public Set<String> getAllAmpAuthCode() {
        Set<String> authCode = new HashSet<>();
        AmpAuthExample ampAuthExample = new AmpAuthExample();
         ampAuthExample.createCriteria().andStatusCdEqualTo(1);
        List<AmpAuthVO> ampAuths = ampAuthMapper.selectByExample(ampAuthExample);
        for (AmpAuthVO ampAuth : ampAuths) {
            authCode.add(ampAuth.getAuthCode());
        }
        return authCode;
    }

    @Override
    public Set<String> getAuthCodeByCondition(Long staffId, Long systemId) {
        Set<String> authCode = new HashSet<>();
        AmpAuthExample ampAuthExample = new AmpAuthExample();
        ampAuthExample.createCriteria().andStatusCdEqualTo(1);
        List<AmpAuthVO> ampAuths = ampAuthMapper.selectByExample(ampAuthExample);
        for (AmpAuthVO ampAuth : ampAuths) {
            authCode.add(ampAuth.getAuthCode());
        }
        return authCode;
    }

    /**
     * 根据对象类型、对象值获取权限信息(用户、角色)
     * 角色获取启动的角色，以及用户拥护的角色，
     * 用于左侧菜单显示以及权限判断
     * @param ampStaffAuthRelDTO
     * @return
     */
     @Override
    public List<AmpMenuVO> getAmpAuthByStaffAuthRel(AmpStaffAuthRelDTO ampStaffAuthRelDTO) {
        log.debug("getAmpAuthByStaffAuthRel入参："+ FastJsonUtils.toJSONString(ampStaffAuthRelDTO));
        List<SysRegisterVO> sysRegisterVOS = null;
        List<AmpStaffAuthVO> ampStaffAuthVOs = new ArrayList<>();;
        List<AmpStaffAuthVO> ampStaffRoleAuthVOs = new ArrayList<>();;
        List<AmpStaffAuthVO> ampStaffAuthVOsAll = new ArrayList<>();
        List<AmpMenuVO> ampAuthVOs = null;
        List<AmpMenuVO> ampAuths = new ArrayList<>();
        SysRegisterVO sysRegisterVO = null;
        //1.根据系统编码取出系统系统
        SysRegisterExample sysRegisterExample = new SysRegisterExample();
        SysRegisterExample.Criteria criteriaSysRegister = sysRegisterExample.createCriteria();
        if (ampStaffAuthRelDTO.getSystemId()!=null) {
            criteriaSysRegister.andSystemIdEqualTo(ampStaffAuthRelDTO.getSystemId());
        }
        sysRegisterVOS = sysRegisterMapper.selectByExample(sysRegisterExample);
        if (CollectionUtil.isNotEmpty(sysRegisterVOS)) {
            sysRegisterVO = sysRegisterVOS.get(0);
        } else {
            return null;
        }
        //超级管理员处理
        if(ampStaffAuthRelDTO.getStaffId().toString().equals(serviceConstConfig.getAdminId())){
            AmpAuthDTO ampAuthDTO = new AmpAuthDTO();
            ampAuthDTO.setSystemId(sysRegisterVO.getSystemId());
            ampAuthDTO.setStatusCd(1);
            ampAuthDTO.setAuthTypes(ampStaffAuthRelDTO.getAuthTypes());
            ampAuths = getAmpAuthByCondition(ampAuthDTO);
            if(ListUtils.compare(ampStaffAuthRelDTO.getAuthTypes(),Arrays.asList(new String[]{"url","expand"}))){
                ListUtils.sortByMethod(ampAuths,"getDispOrder",ListUtils.ASC);
            }
            return ampAuths;
        }
        //合并用户、角色的权限
        //用户权限
        if(ampStaffAuthRelDTO.getStaffId() != null){
            AmpStaffAuthExample ampStaffAuthExample = new AmpStaffAuthExample();
            AmpStaffAuthExample.Criteria criteria = ampStaffAuthExample.createCriteria();
            criteria.andObjectIdEqualTo(ampStaffAuthRelDTO.getStaffId());
            criteria.andObjectTypeEqualTo((short)1);
            criteria.andStatusCdEqualTo((short)1);

            ampStaffAuthVOs = ampStaffAuthMapper.selectByExample(ampStaffAuthExample);
        }
        //查找启用的角色（角色停用，则用户拥有的角色失效）
        AmpRoleExample ampRoleExample = new AmpRoleExample();
        AmpRoleExample.Criteria ampRoleCriteria = ampRoleExample.createCriteria();
        if (CollectionUtil.isNotEmpty(ampStaffAuthRelDTO.getRoles())) {
            List<Long> list = ampStaffAuthRelDTO.getRoles().stream().
                    map(Long::parseLong).
                    collect(Collectors.toList());
            ampRoleCriteria.andRoleIdIn(list);
        }
        ampRoleCriteria.andStatusCdEqualTo((short) 1);
        List<AmpRoleVO> ampRoleVOS = ampRoleMapper.selectByExample(ampRoleExample);
        List<Long> roles = new ArrayList<>();
        for (AmpRoleVO ampRoleVO : ampRoleVOS) {
            roles.add(ampRoleVO.getRoleId());
        }
        List<Long> userHasRoles = new ArrayList<>();
        //在角色启用的前提下，查找用户拥有的角色
        if (CollectionUtil.isNotEmpty(roles)) {
            AmpStaffRoleExample ampStaffRoleExample = new AmpStaffRoleExample();
            AmpStaffRoleExample.Criteria criteria = ampStaffRoleExample.createCriteria();
            criteria.andStatusCdEqualTo((short) 1);
            criteria.andStaffIdEqualTo(ampStaffAuthRelDTO.getStaffId());
            criteria.andRoleIdIn(roles);
            List<AmpStaffRoleVO> ampStaffRoleVOS = ampStaffRoleMapper.selectByExample(ampStaffRoleExample);
            for (AmpStaffRoleVO ampStaffRoleVO : ampStaffRoleVOS) {
                userHasRoles.add(ampStaffRoleVO.getRoleId());
            }
        }
        //根据角色查找角色拥有的权限
        if (CollectionUtil.isNotEmpty(userHasRoles)) {
            AmpStaffAuthExample ampStaffAuthExample = new AmpStaffAuthExample();
            AmpStaffAuthExample.Criteria criteria = ampStaffAuthExample.createCriteria();
            criteria.andObjectIdIn(roles);
            criteria.andSystemIdEqualTo(sysRegisterVO.getSystemId());
            criteria.andObjectTypeEqualTo((short) 2);
            criteria.andStatusCdEqualTo((short) 1);
            ampStaffRoleAuthVOs = ampStaffAuthMapper.selectByExample(ampStaffAuthExample);
        }
        //合并用户权限以及角色权限
        ampStaffAuthVOs.addAll(ampStaffRoleAuthVOs);
        Set set = new HashSet(ampStaffAuthVOs);
        ampStaffAuthVOsAll.addAll(set);
        if(CollectionUtil.isEmpty(ampStaffAuthVOsAll)){
            return null;
        }
        //权限过滤
        AmpAuthDTO ampAuthDTO = new AmpAuthDTO();
        ampAuthDTO.setSystemId(sysRegisterVO.getSystemId());
        ampAuthDTO.setStatusCd(1);
        ampAuthDTO.setAuthTypes(ampStaffAuthRelDTO.getAuthTypes());
        ampAuthVOs = getAmpAuthByCondition(ampAuthDTO);
        for (AmpMenuVO ampAuthVO : ampAuthVOs) {
            for (AmpStaffAuthVO ampStaffAuthVO : ampStaffAuthVOsAll) {
                if(ampAuthVO.getAuthId().equals(ampStaffAuthVO.getAuthId())){
                    ampAuths.add(ampAuthVO);
                }
            }

        }
        //升序排序
        if(ListUtils.compare(ampStaffAuthRelDTO.getAuthTypes(),Arrays.asList(new String[]{"url","expand"}))){
            ListUtils.sortByMethod(ampAuths,"getDispOrder",ListUtils.ASC);
        }
        return ampAuths;
    }

    @Override
    public List<AmpMenuVO> getAmpAuth(AmpStaffAuthRelDTO ampStaffAuthRelDTO) {
        List<SysRegisterVO> sysRegisterVOS = null;
        List<AmpStaffAuthVO> ampStaffAuthVOs = new ArrayList<>();;
        List<AmpStaffAuthVO> ampStaffRoleAuthVOs = new ArrayList<>();;
        List<AmpStaffAuthVO> ampStaffAuthVOsAll = new ArrayList<>();
        List<AmpMenuVO> ampAuthVOs = null;
        List<AmpMenuVO> ampAuths = new ArrayList<>();
        //超级管理员处理
        if(ampStaffAuthRelDTO.getStaffId().toString().equals(serviceConstConfig.getAdminId())){
            AmpAuthDTO ampAuthDTO = new AmpAuthDTO();
            ampAuthDTO.setSystemId(ampStaffAuthRelDTO.getSystemId());
            ampAuthDTO.setStatusCd(1);
            ampAuthDTO.setAuthTypes(ampStaffAuthRelDTO.getAuthTypes());
            ampAuths = getAmpAuthByCondition(ampAuthDTO);
            if(ListUtils.compare(ampStaffAuthRelDTO.getAuthTypes(),Arrays.asList(new String[]{"url","expand"}))){
                ListUtils.sortByMethod(ampAuths,"getDispOrder",ListUtils.ASC);
            }
            return ampAuths;
        }
        //合并用户、角色的权限
        //用户权限
        if(ampStaffAuthRelDTO.getStaffId() != null){
            AmpStaffAuthExample ampStaffAuthExample = new AmpStaffAuthExample();
            AmpStaffAuthExample.Criteria criteria = ampStaffAuthExample.createCriteria();
            criteria.andObjectIdEqualTo(ampStaffAuthRelDTO.getStaffId());
            criteria.andObjectTypeEqualTo((short)1);
            criteria.andStatusCdEqualTo((short)1);
            ampStaffAuthVOs = ampStaffAuthMapper.selectByExample(ampStaffAuthExample);
        }
        //查找启用的角色（角色停用，则用户拥有的角色失效）
        AmpRoleExample ampRoleExample = new AmpRoleExample();
        AmpRoleExample.Criteria ampRoleCriteria = ampRoleExample.createCriteria();
        if (CollectionUtil.isNotEmpty(ampStaffAuthRelDTO.getRoles())) {
            List<Long> list = ampStaffAuthRelDTO.getRoles().stream().
                    map(Long::parseLong).
                    collect(Collectors.toList());
            ampRoleCriteria.andRoleIdIn(list);
        }
        ampRoleCriteria.andStatusCdEqualTo((short) 1);
        List<AmpRoleVO> ampRoleVOS = ampRoleMapper.selectByExample(ampRoleExample);
        List<Long> roles = new ArrayList<>();
        for (AmpRoleVO ampRoleVO : ampRoleVOS) {
            roles.add(ampRoleVO.getRoleId());
        }
        List<Long> userHasRoles = new ArrayList<>();
        //在角色启用的前提下，查找用户拥有的角色
        if (CollectionUtil.isNotEmpty(roles)) {
            AmpStaffRoleExample ampStaffRoleExample = new AmpStaffRoleExample();
            AmpStaffRoleExample.Criteria criteria = ampStaffRoleExample.createCriteria();
            criteria.andStatusCdEqualTo((short) 1);
            criteria.andStaffIdEqualTo(ampStaffAuthRelDTO.getStaffId());
            criteria.andRoleIdIn(roles);
            List<AmpStaffRoleVO> ampStaffRoleVOS = ampStaffRoleMapper.selectByExample(ampStaffRoleExample);
            for (AmpStaffRoleVO ampStaffRoleVO : ampStaffRoleVOS) {
                userHasRoles.add(ampStaffRoleVO.getRoleId());
            }
        }
        //根据角色查找角色拥有的权限
        if (CollectionUtil.isNotEmpty(userHasRoles)) {
            AmpStaffAuthExample ampStaffAuthExample = new AmpStaffAuthExample();
            AmpStaffAuthExample.Criteria criteria = ampStaffAuthExample.createCriteria();
            criteria.andObjectIdIn(roles);
            criteria.andSystemIdEqualTo(ampStaffAuthRelDTO.getSystemId());
            criteria.andObjectTypeEqualTo((short) 2);
            criteria.andStatusCdEqualTo((short) 1);
            ampStaffRoleAuthVOs = ampStaffAuthMapper.selectByExample(ampStaffAuthExample);
        }
        //合并用户权限以及角色权限
        ampStaffAuthVOs.addAll(ampStaffRoleAuthVOs);
        Set set = new HashSet(ampStaffAuthVOs);
        ampStaffAuthVOsAll.addAll(set);
        if(CollectionUtil.isEmpty(ampStaffAuthVOsAll)){
            return null;
        }
        //权限过滤
        AmpAuthDTO ampAuthDTO = new AmpAuthDTO();
        ampAuthDTO.setSystemId(ampStaffAuthRelDTO.getSystemId());
        ampAuthDTO.setStatusCd(1);
        ampAuthDTO.setAuthTypes(ampStaffAuthRelDTO.getAuthTypes());
        ampAuthVOs = getAmpAuthByCondition(ampAuthDTO);
        for (AmpMenuVO ampAuthVO : ampAuthVOs) {
            for (AmpStaffAuthVO ampStaffAuthVO : ampStaffAuthVOsAll) {
                if(ampAuthVO.getAuthId().equals(ampStaffAuthVO.getAuthId())){
                    ampAuths.add(ampAuthVO);
                }
            }

        }
        return ampAuths;
    }


    @Override
    public List<AmpMenuVO> getAmpAuthByCondition(AmpAuthDTO ampAuthDTO) {
        AmpAuthExample ampAuthExample = new AmpAuthExample();
        AmpAuthExample.Criteria criteria = ampAuthExample.createCriteria();
        if(StringUtils.isNotBlank(ampAuthDTO.getAuthCode())){
            criteria.andAuthCodeEqualTo(ampAuthDTO.getAuthCode());
        }
        if(!CollectionUtils.isEmpty(ampAuthDTO.getAuthTypes())){
            criteria.andAuthTypeIn(ampAuthDTO.getAuthTypes());
        }
        if(StringUtils.isNotBlank(ampAuthDTO.getAuthType())){
            criteria.andAuthTypeEqualTo(ampAuthDTO.getAuthType());
        }
        if(StringUtils.isNotBlank(ampAuthDTO.getUrl())){
            criteria.andUrlEqualTo(ampAuthDTO.getUrl());
        }
        if(ampAuthDTO.getAuthId() != null){
            criteria.andAuthIdEqualTo(ampAuthDTO.getAuthId());
        }
        if(ampAuthDTO.getParentId() != null){
            criteria.andParentIdEqualTo(ampAuthDTO.getParentId());
        }
        if(ampAuthDTO.getCreatedStaffId() != null){
            criteria.andCreatedStaffIdEqualTo(ampAuthDTO.getCreatedStaffId());
        }
        if(ampAuthDTO.getSystemId() != null){
            criteria.andSystemIdEqualTo(ampAuthDTO.getSystemId());
        }
        criteria.andStatusCdEqualTo(1);
        return ampAuthMapper.selectByExample4Menu(ampAuthExample);
    }

     @Override
    public List<AmpAuthVO> findAuthByExample(AmpAuthDTO ampAuthDTO) {
        AmpAuthExample authExample = new AmpAuthExample();
        AmpAuthExample.Criteria criteria = authExample.createCriteria();
        boolean is = false;
        if(StringUtils.isNotEmpty(ampAuthDTO.getAuthName())){
            criteria.andAuthNameLike("%"+ampAuthDTO.getAuthName()+"%");
            is = true;
        }
        if(StringUtils.isNotEmpty(ampAuthDTO.getUrl())){
            criteria.andUrlLike("%"+ampAuthDTO.getUrl()+"%");
            is = true;
        }
        criteria.andSystemIdEqualTo(ampAuthDTO.getSystemId());
        criteria.andStatusCdEqualTo(1);
        authExample.setDistinct(true);
        authExample.setOrderByClause("DISP_ORDER");
//        AmpAuth ampAuth = new AmpAuth();
//        BeanUtils.copyProperties(ampAuthDTO,ampAuth);
//        if(is){
//            List<AmpAuthVO> ampAuthVOS = ampAuthMapper.selectByExample(authExample);
//            List<AmpAuthVO> ampAuthVOS2 = ampAuthVOS;
//            AmpAuthExample authExample2 = null;
//            AmpAuthExample.Criteria criteria2 = null;
//            while (true){
//                if(ampAuthVOS2.size()>0){
//                    authExample2 = new AmpAuthExample();
//                    criteria2 = authExample2.createCriteria();
//                    List<Long> authIds = new ArrayList<>();
//                    for (AmpAuthVO ampAuthVO:ampAuthVOS2){
//                        authIds.add(ampAuthVO.getAuthId());
//                    }
//                    criteria2.andParentIdIn(authIds);
//                    criteria2.andSystemIdEqualTo(ampAuthDTO.getSystemId());
//                    criteria2.andStatusCdEqualTo(1);
//                    authExample2.setDistinct(true);
//                    authExample2.setOrderByClause("DISP_ORDER");
//                    ampAuthVOS2 = ampAuthMapper.selectByExample(authExample2);
//                    ampAuthVOS.addAll(ampAuthVOS2);
//                }else{
//                    break;
//                }
//            }
//            List<AmpAuthVO> newList  =   new  ArrayList<>();
//            for (AmpAuthVO ampAuthVO:ampAuthVOS){
//                boolean is2 = true;
//                for (AmpAuthVO ampAuthVO1:newList){
//                    if(ampAuthVO1.getAuthId().equals(ampAuthVO.getAuthId())){
//                        is2 = false;
//                        break;
//                    }
//                }
//                if(is2){
//                    newList.add(ampAuthVO);
//                }
//            }
//            return newList;
//        }else{
//            return ampAuthMapper.selectByExample(authExample);
//        }
         return ampAuthMapper.selectByExample(authExample);
    }

    @Transactional(propagation= Propagation.REQUIRED, rollbackFor=Exception.class)
    @Override
    public int delete(Long authId) {
        AmpAuthExample ampAuthExample = new AmpAuthExample();
        AmpAuthExample.Criteria criteria = ampAuthExample.createCriteria();
        if(authId!=null){
            criteria.andAuthIdEqualTo(authId);
        }
        AmpAuth ampAuth = new AmpAuth();
        ampAuth.setVersion(new Date());
        ampAuth.setStatusCd(2);
        AmpAuthExample ampAuthExampleSon = new AmpAuthExample();
        AmpAuthExample.Criteria criteriaSon = ampAuthExampleSon.createCriteria();
        if(authId!=null){
        	criteriaSon.andParentIdEqualTo(authId);
        }
        AmpAuth ampAuthSon = new AmpAuth();
        ampAuthSon.setVersion(new Date());
        ampAuthSon.setStatusCd(2);
        if(ampAuthMapper.deleteByExample(ampAuth,ampAuthExample)>=1){
        	ampAuthMapper.deleteByExample(ampAuthSon, ampAuthExampleSon);
        	return 1;
        } else {
        	return -1;
        }
    }

    @Transactional(propagation= Propagation.REQUIRED, rollbackFor=Exception.class)
    @Override
    public int insert(AmpAuthDTO ampAuthDTO) {
        AmpAuth ampAuth = new AmpAuth();
        BeanUtils.copyProperties(ampAuthDTO,ampAuth);
        ampAuth.setCreatedDt(new Date());
        ampAuth.setVersion(new Date());
        ampAuth.setStatusCd(1);
        ampAuth.setAuthCode(UUIDUtils.getRandom32PK());
        return ampAuthMapper.insert(ampAuth);
    }

    @Transactional(propagation= Propagation.REQUIRED, rollbackFor=Exception.class)
    @Override
    public int update(AmpAuthDTO ampAuthDTO) {
        AmpAuthExample ampAuthExample = new AmpAuthExample();
        AmpAuthExample.Criteria criteria = ampAuthExample.createCriteria();
        if(ampAuthDTO.getAuthId() != null){
            criteria.andAuthIdEqualTo(ampAuthDTO.getAuthId());
        }
        AmpAuth ampAuth = new AmpAuth();
        ampAuth.setVersion(new Date());
        BeanUtils.copyProperties(ampAuthDTO,ampAuth);
        return ampAuthMapper.updateByExample(ampAuth,ampAuthExample);
    }
}
